Read in Script
source("Safegraph_Script.R")
NAs introduced by coercion
rm(list=ls()[! ls() %in% c("rural_ipums","ruca", "subset_glass",
"poverty_ipums", "pct_chg_aug",
"industry_ipums", "aug_combined",
"buffer1_vec","buffer2_perim_vec",
"buffer2_vec", "cf_bf1", "cf_bf2", "gfperimvec",
"not_zcta", "rural_ruca",
'%notin%', 'pp1', 'pp2', 'aug_combined', 'com')])
Read in Spatial Plots
plot.new()
rasterImage(pp1,0,0,1,1)

plot.new()
rasterImage(pp2,0,0,1,1)

Initially a single 20-acre brush fire, it rapidly grew and merged with two smaller fires that expanded to 11,000 acres during the night of September 27 into September 28.
The Glass Fire was fully contained on October 20, 2020, after burning over 67,484 acres and destroying 1,555 structures, including 308 homes and 343 commercial buildings in Napa County, as well as 334 homes in Sonoma County
Data Tables (Descriptives)
Using shape files from the GlassFire, 10 km buffers were used to create the first buffer (BF1), 10km surrounding BF1 creates the second buffer (BF2).
Each perimeter has unique ZCTA that is exclusive to their perimeter.
DT::datatable(com %>%
filter(june != 'June') %>%
mutate(new_date = as.POSIXct(strptime(date_range_start, "%Y-%m-%d"))) %>%
mutate(week = as_date(new_date)) %>%
group_by(city, zcta, week, fire_cat,
Poverty_Dummy_75, Agr_Dummy_75,
Rural_Dummy_R) %>%
summarize(sum_visit = sum(raw_visit_counts), .groups = 'drop'),
caption = 'Descriptive Statistics of August Mobility',
filter = "top",
extensions = c("SearchPanes", "Select", "Buttons"),
options = list(dom = "Btip",buttons = list("searchPanes")))
DT::datatable(com %>%
filter(june == 'June') %>%
mutate(new_date = as.POSIXct(strptime(date_range_start, "%Y-%m-%d"))) %>%
mutate(week = as_date(new_date)) %>%
group_by(city, zcta, week, fire_cat,
Poverty_Dummy_75, Agr_Dummy_75,
Rural_Dummy_R) %>%
summarize(sum_visit = sum(raw_visit_counts), .groups = 'drop'),
caption = 'Descriptive Statistics of June Mobility',
filter = "top",
extensions = c("SearchPanes", "Select", "Buttons"),
options = list(dom = "Btip",buttons = list("searchPanes")))
Visualizations
Percent Change Using Fire Category and June as Baseline
pct_chg_aug %>%
na.omit() %>%
group_by(week,zcta,fire_cat) %>%
summarize(med = median(pct_chg_mon_f), .groups = 'drop') %>%
ggplot(data =., aes(x = week, y = med, group = zcta)) +
scale_color_manual(values=c('Blue','Green', 'Red')) +
geom_line(aes(colour=fire_cat), alpha = 0.2) +
geom_point(aes(colour = fire_cat), alpha = 0.8) +
ylim(-50,200) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +# week of Oct 12
theme(axis.text.x = element_text(angle = 0)) +
labs(x="Date", y="Median Percent Change (Divide by 100)") +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line = element_line(colour = "black")) +
annotate("rect", xmin = as.Date("2020-09-21"), xmax = as.Date("2020-10-12"),
ymin = -50.00, ymax = 150.00 ,
alpha = 0, color= "orange") +
ggtitle("Percent Change Mobility by Fire Category")

When looking at mobility: + Week of June 6, 2020 to the week of June 22, 2020 is used as a baseline + Percent change is calculated by week to week in each consecutive week in June + The median of percent change is then grouped by fire category in June and is then officially the baseline for August mobility + Then the percent change of August is then used for each consecutive week in August (August 31 - October 12) + A calculation of percent change is taken by using the weekly percentage change for August in relation to the fire category median percent change.
| GF |
0.02 |
| BF1 |
0.03 |
| BF2 |
0.04 |
Percent Change of Mobility by Rural/ Fire Category and June as Baseline
pct_chg_aug %>%
na.omit() %>%
group_by(week,zcta,Rural_Dummy_R, fire_cat) %>%
summarize(med = median(pct_chg_mon_f), .groups = 'drop') %>%
ggplot(data =., aes(x = week, y = med, group = zcta)) +
scale_color_manual(values=c('Blue','Green', 'Red')) +
geom_line(aes(colour=Rural_Dummy_R), alpha = 0.2) +
geom_point(aes(colour = Rural_Dummy_R), alpha = 0.8) +
ylim(-50,200) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +# week of Oct 12
theme(axis.text.x = element_text(angle = 0)) +
labs(x="Date", y="Median Percent Change (Divide by 100") +
facet_wrap(vars(fire_cat), nrow = 3) +
ggtitle("Percent Change Mobility by Fire Category and Rural")

pct_chg_aug %>%
na.omit() %>%
group_by(week,zcta, fire_cat) %>%
group_by(Rural_Dummy_R, week, fire_cat) %>%
summarize(med = median(pct_chg_mon_f), .groups ='drop') %>%
ggplot(data =., aes(x = week, y = med, group = Rural_Dummy_R)) +
scale_color_manual(values=c('Blue','Green', 'Red')) +
geom_line(aes(colour=Rural_Dummy_R)) +
geom_point(size = 2) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +# week of Oct 12
theme(axis.text.x = element_text(angle = 0)) + facet_wrap(vars(fire_cat), nrow = 3) +ylim(-50,50) +
ggtitle("Percent Change Mobility by Fire Category and Rural (Collapsed)") +
labs(x="Date", y="Median Percent Change (Divide by 100")

pct_chg_aug %>%
na.omit() %>%
group_by(week,zcta) %>%
group_by(Rural_Dummy_R, week, fire_cat) %>%
filter(fire_cat == 'GF') %>%
summarize(med = median(pct_chg_mon_f), .groups ='drop') %>%
ggplot(data =., aes(x = week, y = med, group = Rural_Dummy_R)) +
scale_color_manual(values=c('Blue','Green', 'Red')) +
geom_line(aes(colour=Rural_Dummy_R)) +
geom_point(size = 2) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +# week of Oct 12
theme(axis.text.x = element_text(angle = 0)) +
labs(x="Date", y="Median Percent Change (Divide by 100)") +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line = element_line(colour = "black")) +
annotate("rect", xmin = as.Date("2020-09-21"), xmax = as.Date("2020-10-12"),
ymin = -20, ymax = 60 ,
alpha = 0, color= "orange") +
ggtitle("Median Raw Visits by Date (GF/Collapsed)")

Percent Change of Mobility by Agriculture/ Fire Category and June as Baseline
pct_chg_aug %>%
na.omit() %>%
group_by(week,zcta,Agr_Dummy_75, fire_cat) %>%
summarize(med = median(pct_chg_mon_f), .groups = 'drop') %>%
ggplot(data =., aes(x = week, y = med, group = zcta)) +
scale_color_manual(values=c('Blue','Green', 'Red')) +
geom_line(aes(colour=Agr_Dummy_75), alpha = 0.2) +
geom_point(aes(colour = Agr_Dummy_75), alpha = 0.8) +
ylim(-50,200) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +# week of Oct 12
theme(axis.text.x = element_text(angle = 0)) +
labs(x="Date", y="Median Percent Change") + facet_wrap(vars(fire_cat), nrow = 3)

# Agriculture BY Fire Cat
pct_chg_aug %>%
na.omit() %>%
group_by(week,zcta, fire_cat) %>%
group_by(Agr_Dummy_75, week, fire_cat) %>%
summarize(med = median(pct_chg_mon_f), .groups ='drop') %>%
ggplot(data =., aes(x = week, y = med, group = Agr_Dummy_75)) +
scale_color_manual(values=c('Blue','Green', 'Red')) +
geom_line(aes(colour=Agr_Dummy_75)) +
geom_point(size = 2) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +# week of Oct 12
theme(axis.text.x = element_text(angle = 0)) + facet_wrap(vars(fire_cat), nrow = 3) +ylim(-50,50)
pct_chg_aug %>%
na.omit() %>%
group_by(week,zcta) %>%
group_by(Agr_Dummy_75, week, fire_cat) %>%
filter(fire_cat == 'GF') %>%
summarize(med = median(pct_chg_mon_f), .groups ='drop') %>%
ggplot(data =., aes(x = week, y = med, group = Agr_Dummy_75)) +
scale_color_manual(values=c('Blue','Green', 'Red')) +
geom_line(aes(colour=Agr_Dummy_75)) +
geom_point(size = 2) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +# week of Oct 12
theme(axis.text.x = element_text(angle = 0)) +
labs(x="Date", y="Median Percent Change") +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line = element_line(colour = "black")) +
annotate("rect", xmin = as.Date("2020-09-21"), xmax = as.Date("2020-10-12"),
ymin = -20, ymax = 60 ,
alpha = 0, color= "orange")
ggtitle("Median Raw Visits by Date")
Percent Change of Mobility by Poverty/ Fire Category and June as Baseline
pct_chg_aug %>%
na.omit() %>%
group_by(week,zcta,Poverty_Dummy_75, fire_cat) %>%
summarize(med = median(pct_chg_mon_f), .groups = 'drop') %>%
ggplot(data =., aes(x = week, y = med, group = zcta)) +
scale_color_manual(values=c('Blue','Green', 'Red')) +
geom_line(aes(colour=Poverty_Dummy_75), alpha = 0.2) +
geom_point(aes(colour = Poverty_Dummy_75), alpha = 0.8) +
ylim(-50,200) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +# week of Oct 12
theme(axis.text.x = element_text(angle = 0)) +
labs(x="Date", y="Median Percent Change") + facet_wrap(vars(fire_cat), nrow = 3)

# Poverty BY Fire Cat
pct_chg_aug %>%
na.omit() %>%
group_by(week,zcta, fire_cat) %>%
group_by(Poverty_Dummy_75, week, fire_cat) %>%
summarize(med = median(pct_chg_mon_f), .groups ='drop') %>%
ggplot(data =., aes(x = week, y = med, group = Poverty_Dummy_75)) +
scale_color_manual(values=c('Blue','Green', 'Red')) +
geom_line(aes(colour=Poverty_Dummy_75)) +
geom_point(size = 2) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +# week of Oct 12
theme(axis.text.x = element_text(angle = 0)) + facet_wrap(vars(fire_cat), nrow = 3) + ylim(-75,100)

pct_chg_aug %>%
na.omit() %>%
group_by(week,zcta) %>%
group_by(Poverty_Dummy_75, week, fire_cat) %>%
filter(fire_cat == 'GF') %>%
summarize(med = median(pct_chg_mon_f), .groups ='drop') %>%
ggplot(data =., aes(x = week, y = med, group = Poverty_Dummy_75)) +
scale_color_manual(values=c('Blue','Green', 'Red')) +
geom_line(aes(colour=Poverty_Dummy_75)) +
geom_point(size = 2) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +# week of Oct 12
theme(axis.text.x = element_text(angle = 0)) +
labs(x="Date", y="Median Percent Change") +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line = element_line(colour = "black")) +
annotate("rect", xmin = as.Date("2020-09-21"), xmax = as.Date("2020-10-12"),
ymin = -25, ymax = 60 ,
alpha = 0, color= "orange")

ggtitle("Median Raw Visits by Date")
$title
[1] "Median Raw Visits by Date"
attr(,"class")
[1] "labels"
Looking at PM25 Levels
Grouped by Rural/Urban
pct_chg_aug %>%
na.omit() %>%
inner_join(., subset_glass, by = c('zcta' = 'zcta', 'week' = 'date')) %>%
select(zcta, fire_cat, week, PM25, wf_pm25_imp, bins, pct_chg_mon_z, Rural_Dummy_R) %>%
group_by(week,zcta) %>%
arrange(zcta) %>%
ggplot(data = ., aes(x = week, y = PM25,
color = Rural_Dummy_R)) +
geom_point(aes(color = Rural_Dummy_R), alpha = .5) +
scale_color_manual(values=c('Blue','Green')) +
geom_smooth(se = F) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +
labs(title="PM25 Values by Date and Category") +
labs(x="Date", y="PM25 Values") +
labs(color='Nation') +
annotate("rect", xmin = as.Date("2020-09-21"), xmax = as.Date("2020-10-12"),
ymin = 0, ymax = 100 ,
alpha = 0, color= "orange") + facet_wrap(vars(fire_cat), nrow = 3)

Grouped by Agricultural
pct_chg_aug %>%
na.omit() %>%
inner_join(., subset_glass, by = c('zcta' = 'zcta', 'week' = 'date')) %>%
select(zcta, fire_cat, week, PM25, wf_pm25_imp, bins, pct_chg_mon_z, Agr_Dummy_75) %>%
group_by(week,zcta) %>%
arrange(zcta) %>%
ggplot(data = ., aes(x = week, y = PM25,
color = Agr_Dummy_75)) +
geom_point(aes(color = Agr_Dummy_75), alpha = .5) +
scale_color_manual(values=c('Blue','Green')) +
geom_smooth(se = F) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +
labs(title="PM25 Values by Date and Category") +
labs(x="Date", y="PM25 Values") +
labs(color='Nation') +
annotate("rect", xmin = as.Date("2020-09-21"), xmax = as.Date("2020-10-12"),
ymin = 0, ymax = 100 ,
alpha = 0, color= "orange") + facet_wrap(vars(fire_cat), nrow = 3)

Grouped by Poverty
pct_chg_aug %>%
na.omit() %>%
inner_join(., subset_glass, by = c('zcta' = 'zcta', 'week' = 'date')) %>%
select(zcta, fire_cat, week, PM25, wf_pm25_imp, bins, pct_chg_mon_z, Poverty_Dummy_75) %>%
group_by(week,zcta) %>%
arrange(zcta) %>%
ggplot(data = ., aes(x = week, y = PM25,
color = Poverty_Dummy_75)) +
geom_point(aes(color = Poverty_Dummy_75), alpha = .5) +
scale_color_manual(values=c('Blue','Green')) +
geom_smooth(se = F) +
scale_x_date(breaks = "1 week", limits = as.Date(c("2020-08-31", "2020-10-12"))) +
labs(title="PM25 Values by Date and Category") +
labs(x="Date", y="PM25 Values") +
labs(color='Nation') +
annotate("rect", xmin = as.Date("2020-09-21"), xmax = as.Date("2020-10-12"),
ymin = 0, ymax = 100 ,
alpha = 0, color= "orange") + facet_wrap(vars(fire_cat), nrow = 3)

LS0tCnRpdGxlOiAiU2FmZUdyYXBoIE1vYmlsaXR5IEVEQSBNYXJrZG93biIKYXV0aG9yOiAiQW5kcmV3IExhaSIKZGF0ZTogIjMwLzA0LzIwMjIiCm91dHB1dDogICAKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdGhlbWU6IHNwYWNlbGFiCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgojIyBSZWFkIGluIFNjcmlwdApgYGB7ciwgbWVzc2FnZSA9IEZBTFNFfQpzb3VyY2UoIlNhZmVncmFwaF9TY3JpcHQuUiIpCmBgYAoKYGBge3J9CnJtKGxpc3Q9bHMoKVshIGxzKCkgJWluJSBjKCJydXJhbF9pcHVtcyIsInJ1Y2EiLCAic3Vic2V0X2dsYXNzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJwb3ZlcnR5X2lwdW1zIiwgInBjdF9jaGdfYXVnIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJpbmR1c3RyeV9pcHVtcyIsICJhdWdfY29tYmluZWQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgImJ1ZmZlcjFfdmVjIiwiYnVmZmVyMl9wZXJpbV92ZWMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgImJ1ZmZlcjJfdmVjIiwgImNmX2JmMSIsICJjZl9iZjIiLCAiZ2ZwZXJpbXZlYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJub3RfemN0YSIsICJydXJhbF9ydWNhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICclbm90aW4lJywgJ3BwMScsICdwcDInLCAnYXVnX2NvbWJpbmVkJywgJ2NvbScpXSkKYGBgCgojIyBSZWFkIGluIFNwYXRpYWwgUGxvdHMKYGBge3J9CnBsb3QubmV3KCkgCnJhc3RlckltYWdlKHBwMSwwLDAsMSwxKQpgYGAKCgpgYGB7cn0KcGxvdC5uZXcoKSAKcmFzdGVySW1hZ2UocHAyLDAsMCwxLDEpCmBgYApJbml0aWFsbHkgYSBzaW5nbGUgMjAtYWNyZSBicnVzaCBmaXJlLCBpdCByYXBpZGx5IGdyZXcgYW5kIG1lcmdlZCB3aXRoIHR3byBzbWFsbGVyIGZpcmVzIHRoYXQgZXhwYW5kZWQgdG8gMTEsMDAwIGFjcmVzIGR1cmluZyB0aGUgbmlnaHQgb2YgU2VwdGVtYmVyIDI3IGludG8gU2VwdGVtYmVyIDI4LgoKVGhlIEdsYXNzIEZpcmUgd2FzIGZ1bGx5IGNvbnRhaW5lZCBvbiBPY3RvYmVyIDIwLCAyMDIwLCBhZnRlciBidXJuaW5nIG92ZXIgNjcsNDg0IGFjcmVzIGFuZCBkZXN0cm95aW5nIDEsNTU1IHN0cnVjdHVyZXMsIGluY2x1ZGluZyAzMDggaG9tZXMgYW5kIDM0MyBjb21tZXJjaWFsIGJ1aWxkaW5ncyBpbiBOYXBhIENvdW50eSwgYXMgd2VsbCBhcyAzMzQgaG9tZXMgaW4gU29ub21hIENvdW50eQoKCgojIyBEYXRhIFRhYmxlcyAoRGVzY3JpcHRpdmVzKQoKCkZpcmUgQ2F0ZWdvcnkgfCBUb3RhbCBaQ1RBCi0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tCkdGICAgICAgICAgICAgfCA4CkJGMSAgICAgICAgICAgfCAxNwpCRjIgICAgICAgICAgIHwgMTAKCgpVc2luZyBzaGFwZSBmaWxlcyBmcm9tIHRoZSBHbGFzc0ZpcmUsIDEwIGttIGJ1ZmZlcnMgd2VyZSB1c2VkIHRvIGNyZWF0ZSB0aGUgZmlyc3QgYnVmZmVyIChCRjEpLCAxMGttIHN1cnJvdW5kaW5nIEJGMSBjcmVhdGVzIHRoZSBzZWNvbmQgYnVmZmVyIChCRjIpLgoKRWFjaCBwZXJpbWV0ZXIgaGFzIHVuaXF1ZSBaQ1RBIHRoYXQgaXMgZXhjbHVzaXZlIHRvIHRoZWlyIHBlcmltZXRlci4gIAoKCmBgYHtyfQpEVDo6ZGF0YXRhYmxlKGNvbSAlPiUKICAgICAgICAgICAgICAgIGZpbHRlcihqdW5lICE9ICdKdW5lJykgJT4lCiAgICAgICAgICAgICAgICBtdXRhdGUobmV3X2RhdGUgPSBhcy5QT1NJWGN0KHN0cnB0aW1lKGRhdGVfcmFuZ2Vfc3RhcnQsICIlWS0lbS0lZCIpKSkgJT4lCiAgICAgICAgICAgICAgICBtdXRhdGUod2VlayA9IGFzX2RhdGUobmV3X2RhdGUpKSAlPiUKICAgICAgICAgICAgICAgIGdyb3VwX2J5KGNpdHksIHpjdGEsIHdlZWssIGZpcmVfY2F0LCAKICAgICAgICAgICAgICAgICAgICAgICAgIFBvdmVydHlfRHVtbXlfNzUsIEFncl9EdW1teV83NSwKICAgICAgICAgICAgICAgICAgICAgICAgIFJ1cmFsX0R1bW15X1IpICU+JQogICAgICAgICAgICAgICAgc3VtbWFyaXplKHN1bV92aXNpdCA9IHN1bShyYXdfdmlzaXRfY291bnRzKSwgLmdyb3VwcyA9ICdkcm9wJyksIAogICAgICAgICAgICAgIGNhcHRpb24gPSAnRGVzY3JpcHRpdmUgU3RhdGlzdGljcyBvZiBBdWd1c3QgTW9iaWxpdHknLCAKICAgICAgICAgICAgICBmaWx0ZXIgPSAidG9wIiwKICAgICAgICAgICAgICBleHRlbnNpb25zID0gYygiU2VhcmNoUGFuZXMiLCAiU2VsZWN0IiwgIkJ1dHRvbnMiKSwKICAgICAgICAgICAgICBvcHRpb25zID0gbGlzdChkb20gPSAiQnRpcCIsYnV0dG9ucyA9IGxpc3QoInNlYXJjaFBhbmVzIikpKQpgYGAKCgpgYGB7cn0KRFQ6OmRhdGF0YWJsZShjb20gJT4lCiAgICAgICAgICAgICAgICBmaWx0ZXIoanVuZSA9PSAnSnVuZScpICU+JQogICAgICAgICAgICAgICAgbXV0YXRlKG5ld19kYXRlID0gYXMuUE9TSVhjdChzdHJwdGltZShkYXRlX3JhbmdlX3N0YXJ0LCAiJVktJW0tJWQiKSkpICU+JQogICAgICAgICAgICAgICAgbXV0YXRlKHdlZWsgPSBhc19kYXRlKG5ld19kYXRlKSkgJT4lCiAgICAgICAgICAgICAgICBncm91cF9ieShjaXR5LCB6Y3RhLCB3ZWVrLCBmaXJlX2NhdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBQb3ZlcnR5X0R1bW15Xzc1LCBBZ3JfRHVtbXlfNzUsCiAgICAgICAgICAgICAgICAgICAgICAgICBSdXJhbF9EdW1teV9SKSAgJT4lCiAgICAgICAgICAgICAgc3VtbWFyaXplKHN1bV92aXNpdCA9IHN1bShyYXdfdmlzaXRfY291bnRzKSwgLmdyb3VwcyA9ICdkcm9wJyksIAogICAgICAgICAgICAgIGNhcHRpb24gPSAnRGVzY3JpcHRpdmUgU3RhdGlzdGljcyBvZiBKdW5lIE1vYmlsaXR5JywgCiAgICAgICAgICAgICAgZmlsdGVyID0gInRvcCIsCiAgICAgICAgICAgICAgZXh0ZW5zaW9ucyA9IGMoIlNlYXJjaFBhbmVzIiwgIlNlbGVjdCIsICJCdXR0b25zIiksCiAgICAgICAgICAgICAgb3B0aW9ucyA9IGxpc3QoZG9tID0gIkJ0aXAiLGJ1dHRvbnMgPSBsaXN0KCJzZWFyY2hQYW5lcyIpKSkKYGBgCgojIyBWaXN1YWxpemF0aW9ucwoKCiMjIyBQZXJjZW50IENoYW5nZSBVc2luZyBGaXJlIENhdGVnb3J5IGFuZCBKdW5lIGFzIEJhc2VsaW5lCgoKYGBge3J9CnBjdF9jaGdfYXVnICU+JQogIG5hLm9taXQoKSAlPiUKICBncm91cF9ieSh3ZWVrLHpjdGEsZmlyZV9jYXQpICU+JQogIHN1bW1hcml6ZShtZWQgPSBtZWRpYW4ocGN0X2NoZ19tb25fZiksIC5ncm91cHMgPSAnZHJvcCcpICU+JQogIGdncGxvdChkYXRhID0uLCBhZXMoeCA9IHdlZWssIHkgPSBtZWQsIGdyb3VwID0gemN0YSkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoJ0JsdWUnLCdHcmVlbicsICdSZWQnKSkgKwogIGdlb21fbGluZShhZXMoY29sb3VyPWZpcmVfY2F0KSwgYWxwaGEgPSAwLjIpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBmaXJlX2NhdCksIGFscGhhID0gMC44KSArCiAgeWxpbSgtNTAsMjAwKSArCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIxIHdlZWsiLCBsaW1pdHMgPSBhcy5EYXRlKGMoIjIwMjAtMDgtMzEiLCAiMjAyMC0xMC0xMiIpKSkgKyMgd2VlayBvZiBPY3QgMTIKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApKSArIAogIGxhYnMoeD0iRGF0ZSIsIHk9Ik1lZGlhbiBQZXJjZW50IENoYW5nZSAoRGl2aWRlIGJ5IDEwMCkiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIikpICArCiAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDIwLTA5LTIxIiksIHhtYXggPSBhcy5EYXRlKCIyMDIwLTEwLTEyIiksIAogICAgICAgICAgIHltaW4gPSAtNTAuMDAsIHltYXggPSAxNTAuMDAgLAogICAgICAgICAgICAgYWxwaGEgPSAwLCBjb2xvcj0gIm9yYW5nZSIpICsKICBnZ3RpdGxlKCJQZXJjZW50IENoYW5nZSBNb2JpbGl0eSBieSBGaXJlIENhdGVnb3J5IikKYGBgCgpXaGVuIGxvb2tpbmcgYXQgbW9iaWxpdHk6CiAgKyBXZWVrIG9mIEp1bmUgNiwgMjAyMCB0byB0aGUgd2VlayBvZiBKdW5lIDIyLCAyMDIwIGlzIHVzZWQgYXMgYSBiYXNlbGluZQogICsgUGVyY2VudCBjaGFuZ2UgaXMgY2FsY3VsYXRlZCBieSB3ZWVrIHRvIHdlZWsgaW4gZWFjaCBjb25zZWN1dGl2ZSB3ZWVrIGluIEp1bmUgCiAgKyBUaGUgbWVkaWFuIG9mIHBlcmNlbnQgY2hhbmdlIGlzIHRoZW4gZ3JvdXBlZCBieSBmaXJlIGNhdGVnb3J5IGluIEp1bmUgYW5kIGlzIHRoZW4gb2ZmaWNpYWxseSB0aGUKICBiYXNlbGluZSBmb3IgQXVndXN0IG1vYmlsaXR5CiAgKyBUaGVuIHRoZSBwZXJjZW50IGNoYW5nZSBvZiBBdWd1c3QgaXMgdGhlbiB1c2VkIGZvciBlYWNoIGNvbnNlY3V0aXZlIHdlZWsgaW4gQXVndXN0IChBdWd1c3QgMzEgLSBPY3RvYmVyIDEyKQogICsgQSBjYWxjdWxhdGlvbiBvZiBwZXJjZW50IGNoYW5nZSBpcyB0YWtlbiBieSB1c2luZyB0aGUgd2Vla2x5IHBlcmNlbnRhZ2UgY2hhbmdlIGZvciBBdWd1c3QgaW4gcmVsYXRpb24gdG8gdGhlIGZpcmUgY2F0ZWdvcnkgbWVkaWFuIHBlcmNlbnQgY2hhbmdlLiAgCgoKCkZpcmUgQ2F0ZWdvcnkgfCBNZWRpYW4gUGVyY2VudCBDaGFuZ2UKLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0KR0YgICAgICAgICAgICB8IDAuMDIKQkYxICAgICAgICAgICB8IDAuMDMKQkYyICAgICAgICAgICB8IDAuMDQKCgoKIyMjIFBlcmNlbnQgQ2hhbmdlIG9mIE1vYmlsaXR5IGJ5IFJ1cmFsLyBGaXJlIENhdGVnb3J5IGFuZCBKdW5lIGFzIEJhc2VsaW5lCgpSdXJhbCBDYXRlZ29yeSB8IFRvdGFsIFpDVEEKLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0KUnVyYWwgICAgICAgICB8IDExClVyYmFuICAgICAgICAgfCAyNAoKYGBge3J9CnBjdF9jaGdfYXVnICU+JQogIG5hLm9taXQoKSAlPiUKICBncm91cF9ieSh3ZWVrLHpjdGEsUnVyYWxfRHVtbXlfUiwgZmlyZV9jYXQpICU+JQogIHN1bW1hcml6ZShtZWQgPSBtZWRpYW4ocGN0X2NoZ19tb25fZiksIC5ncm91cHMgPSAnZHJvcCcpICU+JQogIGdncGxvdChkYXRhID0uLCBhZXMoeCA9IHdlZWssIHkgPSBtZWQsIGdyb3VwID0gemN0YSkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoJ0JsdWUnLCdHcmVlbicsICdSZWQnKSkgKwogIGdlb21fbGluZShhZXMoY29sb3VyPVJ1cmFsX0R1bW15X1IpLCBhbHBoYSA9IDAuMikgKwogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IFJ1cmFsX0R1bW15X1IpLCBhbHBoYSA9IDAuOCkgKwogIHlsaW0oLTUwLDIwMCkgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMSB3ZWVrIiwgbGltaXRzID0gYXMuRGF0ZShjKCIyMDIwLTA4LTMxIiwgIjIwMjAtMTAtMTIiKSkpICsjIHdlZWsgb2YgT2N0IDEyCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSkgKyAKICBsYWJzKHg9IkRhdGUiLCB5PSJNZWRpYW4gUGVyY2VudCBDaGFuZ2UgKERpdmlkZSBieSAxMDAiKSArIAogIGZhY2V0X3dyYXAodmFycyhmaXJlX2NhdCksIG5yb3cgPSAzKSArCiAgZ2d0aXRsZSgiUGVyY2VudCBDaGFuZ2UgTW9iaWxpdHkgYnkgRmlyZSBDYXRlZ29yeSBhbmQgUnVyYWwiKQpgYGAKCgpgYGB7cn0KcGN0X2NoZ19hdWcgJT4lCiAgbmEub21pdCgpICU+JQogIGdyb3VwX2J5KHdlZWssemN0YSwgZmlyZV9jYXQpICU+JQogIGdyb3VwX2J5KFJ1cmFsX0R1bW15X1IsIHdlZWssIGZpcmVfY2F0KSAlPiUKICBzdW1tYXJpemUobWVkID0gbWVkaWFuKHBjdF9jaGdfbW9uX2YpLCAuZ3JvdXBzID0nZHJvcCcpICU+JQogIGdncGxvdChkYXRhID0uLCBhZXMoeCA9IHdlZWssIHkgPSBtZWQsIGdyb3VwID0gUnVyYWxfRHVtbXlfUikpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoJ0JsdWUnLCdHcmVlbicsICdSZWQnKSkgKwogIGdlb21fbGluZShhZXMoY29sb3VyPVJ1cmFsX0R1bW15X1IpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMikgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMSB3ZWVrIiwgbGltaXRzID0gYXMuRGF0ZShjKCIyMDIwLTA4LTMxIiwgIjIwMjAtMTAtMTIiKSkpICArIyB3ZWVrIG9mIE9jdCAxMgogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCkpICsgZmFjZXRfd3JhcCh2YXJzKGZpcmVfY2F0KSwgbnJvdyA9IDMpICt5bGltKC01MCw1MCkgKwogIGdndGl0bGUoIlBlcmNlbnQgQ2hhbmdlIE1vYmlsaXR5IGJ5IEZpcmUgQ2F0ZWdvcnkgYW5kIFJ1cmFsIChDb2xsYXBzZWQpIikgKwogIGxhYnMoeD0iRGF0ZSIsIHk9Ik1lZGlhbiBQZXJjZW50IENoYW5nZSAoRGl2aWRlIGJ5IDEwMCIpIApgYGAKCmBgYHtyfQpwY3RfY2hnX2F1ZyAlPiUKICBuYS5vbWl0KCkgJT4lCiAgZ3JvdXBfYnkod2Vlayx6Y3RhKSAlPiUKICBncm91cF9ieShSdXJhbF9EdW1teV9SLCB3ZWVrLCBmaXJlX2NhdCkgJT4lCiAgZmlsdGVyKGZpcmVfY2F0ID09ICdHRicpICU+JQogIHN1bW1hcml6ZShtZWQgPSBtZWRpYW4ocGN0X2NoZ19tb25fZiksIC5ncm91cHMgPSdkcm9wJykgJT4lCiAgZ2dwbG90KGRhdGEgPS4sIGFlcyh4ID0gd2VlaywgeSA9IG1lZCwgZ3JvdXAgPSBSdXJhbF9EdW1teV9SKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygnQmx1ZScsJ0dyZWVuJywgJ1JlZCcpKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvdXI9UnVyYWxfRHVtbXlfUikpICsKICBnZW9tX3BvaW50KHNpemUgPSAyKSArCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIxIHdlZWsiLCBsaW1pdHMgPSBhcy5EYXRlKGMoIjIwMjAtMDgtMzEiLCAiMjAyMC0xMC0xMiIpKSkgKyMgd2VlayBvZiBPY3QgMTIKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApKSArIAogIGxhYnMoeD0iRGF0ZSIsIHk9Ik1lZGlhbiBQZXJjZW50IENoYW5nZSAoRGl2aWRlIGJ5IDEwMCkiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIikpICArCiAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDIwLTA5LTIxIiksIHhtYXggPSBhcy5EYXRlKCIyMDIwLTEwLTEyIiksIAogICAgICAgICAgIHltaW4gPSAtMjAsIHltYXggPSA2MCAsCiAgICAgICAgICAgICBhbHBoYSA9IDAsIGNvbG9yPSAib3JhbmdlIikgKwogIGdndGl0bGUoIk1lZGlhbiBSYXcgVmlzaXRzIGJ5IERhdGUgKEdGL0NvbGxhcHNlZCkiKQpgYGAKCgoKIyMjIFBlcmNlbnQgQ2hhbmdlIG9mIE1vYmlsaXR5IGJ5IEFncmljdWx0dXJlLyBGaXJlIENhdGVnb3J5IGFuZCBKdW5lIGFzIEJhc2VsaW5lCgoKQWdyIENhdGVnb3J5ICAgfCBUb3RhbCBaQ1RBCi0tLS0tLS0tLS0tLS0gIHwgLS0tLS0tLS0tLS0tLQpBZ3I8NzUgICAgICAgICB8IDI2CkFncj43NSAgICAgICAgIHwgOQoKYGBge3J9CnBjdF9jaGdfYXVnICU+JQogIG5hLm9taXQoKSAlPiUKICBncm91cF9ieSh3ZWVrLHpjdGEsQWdyX0R1bW15Xzc1LCBmaXJlX2NhdCkgJT4lCiAgc3VtbWFyaXplKG1lZCA9IG1lZGlhbihwY3RfY2hnX21vbl9mKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgZ2dwbG90KGRhdGEgPS4sIGFlcyh4ID0gd2VlaywgeSA9IG1lZCwgZ3JvdXAgPSB6Y3RhKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygnQmx1ZScsJ0dyZWVuJywgJ1JlZCcpKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvdXI9QWdyX0R1bW15Xzc1KSwgYWxwaGEgPSAwLjIpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBBZ3JfRHVtbXlfNzUpLCBhbHBoYSA9IDAuOCkgKwogIHlsaW0oLTUwLDIwMCkgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMSB3ZWVrIiwgbGltaXRzID0gYXMuRGF0ZShjKCIyMDIwLTA4LTMxIiwgIjIwMjAtMTAtMTIiKSkpICsjIHdlZWsgb2YgT2N0IDEyCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSkgKyAKICBsYWJzKHg9IkRhdGUiLCB5PSJNZWRpYW4gUGVyY2VudCBDaGFuZ2UiKSArIGZhY2V0X3dyYXAodmFycyhmaXJlX2NhdCksIG5yb3cgPSAzKQpgYGAKCmBgYHtyfQojIEFncmljdWx0dXJlIEJZIEZpcmUgQ2F0CnBjdF9jaGdfYXVnICU+JQogIG5hLm9taXQoKSAlPiUKICBncm91cF9ieSh3ZWVrLHpjdGEsIGZpcmVfY2F0KSAlPiUKICBncm91cF9ieShBZ3JfRHVtbXlfNzUsIHdlZWssIGZpcmVfY2F0KSAlPiUKICBzdW1tYXJpemUobWVkID0gbWVkaWFuKHBjdF9jaGdfbW9uX2YpLCAuZ3JvdXBzID0nZHJvcCcpICU+JQogIGdncGxvdChkYXRhID0uLCBhZXMoeCA9IHdlZWssIHkgPSBtZWQsIGdyb3VwID0gQWdyX0R1bW15Xzc1KSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygnQmx1ZScsJ0dyZWVuJywgJ1JlZCcpKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvdXI9QWdyX0R1bW15Xzc1KSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjEgd2VlayIsIGxpbWl0cyA9IGFzLkRhdGUoYygiMjAyMC0wOC0zMSIsICIyMDIwLTEwLTEyIikpKSAgKyMgd2VlayBvZiBPY3QgMTIKCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSkgKyBmYWNldF93cmFwKHZhcnMoZmlyZV9jYXQpLCBucm93ID0gMykgK3lsaW0oLTUwLDUwKQpgYGAKCgoKYGBge3J9CnBjdF9jaGdfYXVnICU+JQogIG5hLm9taXQoKSAlPiUKICBncm91cF9ieSh3ZWVrLHpjdGEpICU+JQogIGdyb3VwX2J5KEFncl9EdW1teV83NSwgd2VlaywgZmlyZV9jYXQpICU+JQogIGZpbHRlcihmaXJlX2NhdCA9PSAnR0YnKSAlPiUKICBzdW1tYXJpemUobWVkID0gbWVkaWFuKHBjdF9jaGdfbW9uX2YpLCAuZ3JvdXBzID0nZHJvcCcpICU+JQogIGdncGxvdChkYXRhID0uLCBhZXMoeCA9IHdlZWssIHkgPSBtZWQsIGdyb3VwID0gQWdyX0R1bW15Xzc1KSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygnQmx1ZScsJ0dyZWVuJywgJ1JlZCcpKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvdXI9QWdyX0R1bW15Xzc1KSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjEgd2VlayIsIGxpbWl0cyA9IGFzLkRhdGUoYygiMjAyMC0wOC0zMSIsICIyMDIwLTEwLTEyIikpKSArIyB3ZWVrIG9mIE9jdCAxMgogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCkpICsgCiAgbGFicyh4PSJEYXRlIiwgeT0iTWVkaWFuIFBlcmNlbnQgQ2hhbmdlIikgKwogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpKSAgKwogICAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gYXMuRGF0ZSgiMjAyMC0wOS0yMSIpLCB4bWF4ID0gYXMuRGF0ZSgiMjAyMC0xMC0xMiIpLCAKICAgICAgICAgICB5bWluID0gLTIwLCB5bWF4ID0gNjAgLAogICAgICAgICAgICAgYWxwaGEgPSAwLCBjb2xvcj0gIm9yYW5nZSIpCiAgZ2d0aXRsZSgiTWVkaWFuIFJhdyBWaXNpdHMgYnkgRGF0ZSIpIApgYGAKCgoKIyMjIFBlcmNlbnQgQ2hhbmdlIG9mIE1vYmlsaXR5IGJ5IFBvdmVydHkvIEZpcmUgQ2F0ZWdvcnkgYW5kIEp1bmUgYXMgQmFzZWxpbmUKCgpQb3YgQ2F0ZWdvcnkgICB8IFRvdGFsIFpDVEEKLS0tLS0tLS0tLS0tLSAgfCAtLS0tLS0tLS0tLS0tClBvdjw3NSAgICAgICAgIHwgMjYKUG92Pjc1ICAgICAgICAgfCA5CgoKCgpgYGB7cn0KcGN0X2NoZ19hdWcgJT4lCiAgbmEub21pdCgpICU+JQogIGdyb3VwX2J5KHdlZWssemN0YSxQb3ZlcnR5X0R1bW15Xzc1LCBmaXJlX2NhdCkgJT4lCiAgc3VtbWFyaXplKG1lZCA9IG1lZGlhbihwY3RfY2hnX21vbl9mKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgZ2dwbG90KGRhdGEgPS4sIGFlcyh4ID0gd2VlaywgeSA9IG1lZCwgZ3JvdXAgPSB6Y3RhKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygnQmx1ZScsJ0dyZWVuJywgJ1JlZCcpKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvdXI9UG92ZXJ0eV9EdW1teV83NSksIGFscGhhID0gMC4yKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gUG92ZXJ0eV9EdW1teV83NSksIGFscGhhID0gMC44KSArCiAgeWxpbSgtNTAsMjAwKSArCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIxIHdlZWsiLCBsaW1pdHMgPSBhcy5EYXRlKGMoIjIwMjAtMDgtMzEiLCAiMjAyMC0xMC0xMiIpKSkgKyMgd2VlayBvZiBPY3QgMTIKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApKSArIAogIGxhYnMoeD0iRGF0ZSIsIHk9Ik1lZGlhbiBQZXJjZW50IENoYW5nZSIpICsgZmFjZXRfd3JhcCh2YXJzKGZpcmVfY2F0KSwgbnJvdyA9IDMpCmBgYAoKYGBge3J9CiMgUG92ZXJ0eSBCWSBGaXJlIENhdApwY3RfY2hnX2F1ZyAlPiUKICBuYS5vbWl0KCkgJT4lCiAgZ3JvdXBfYnkod2Vlayx6Y3RhLCBmaXJlX2NhdCkgJT4lCiAgZ3JvdXBfYnkoUG92ZXJ0eV9EdW1teV83NSwgd2VlaywgZmlyZV9jYXQpICU+JQogIHN1bW1hcml6ZShtZWQgPSBtZWRpYW4ocGN0X2NoZ19tb25fZiksIC5ncm91cHMgPSdkcm9wJykgJT4lCiAgZ2dwbG90KGRhdGEgPS4sIGFlcyh4ID0gd2VlaywgeSA9IG1lZCwgZ3JvdXAgPSBQb3ZlcnR5X0R1bW15Xzc1KSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygnQmx1ZScsJ0dyZWVuJywgJ1JlZCcpKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvdXI9UG92ZXJ0eV9EdW1teV83NSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAyKSArCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIxIHdlZWsiLCBsaW1pdHMgPSBhcy5EYXRlKGMoIjIwMjAtMDgtMzEiLCAiMjAyMC0xMC0xMiIpKSkgICsjIHdlZWsgb2YgT2N0IDEyCgogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCkpICsgZmFjZXRfd3JhcCh2YXJzKGZpcmVfY2F0KSwgbnJvdyA9IDMpICsgeWxpbSgtNzUsMTAwKQpgYGAKCgpgYGB7cn0KcGN0X2NoZ19hdWcgJT4lCiAgbmEub21pdCgpICU+JQogIGdyb3VwX2J5KHdlZWssemN0YSkgJT4lCiAgZ3JvdXBfYnkoUG92ZXJ0eV9EdW1teV83NSwgd2VlaywgZmlyZV9jYXQpICU+JQogIGZpbHRlcihmaXJlX2NhdCA9PSAnR0YnKSAlPiUKICBzdW1tYXJpemUobWVkID0gbWVkaWFuKHBjdF9jaGdfbW9uX2YpLCAuZ3JvdXBzID0nZHJvcCcpICU+JQogIGdncGxvdChkYXRhID0uLCBhZXMoeCA9IHdlZWssIHkgPSBtZWQsIGdyb3VwID0gUG92ZXJ0eV9EdW1teV83NSkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoJ0JsdWUnLCdHcmVlbicsICdSZWQnKSkgKwogIGdlb21fbGluZShhZXMoY29sb3VyPVBvdmVydHlfRHVtbXlfNzUpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMikgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMSB3ZWVrIiwgbGltaXRzID0gYXMuRGF0ZShjKCIyMDIwLTA4LTMxIiwgIjIwMjAtMTAtMTIiKSkpICsjIHdlZWsgb2YgT2N0IDEyCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSkgKyAKICBsYWJzKHg9IkRhdGUiLCB5PSJNZWRpYW4gUGVyY2VudCBDaGFuZ2UiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIikpICArCiAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDIwLTA5LTIxIiksIHhtYXggPSBhcy5EYXRlKCIyMDIwLTEwLTEyIiksIAogICAgICAgICAgIHltaW4gPSAtMjUsIHltYXggPSA2MCAsCiAgICAgICAgICAgICBhbHBoYSA9IDAsIGNvbG9yPSAib3JhbmdlIikKICBnZ3RpdGxlKCJNZWRpYW4gUmF3IFZpc2l0cyBieSBEYXRlIikKYGBgCgojIyMgTG9va2luZyBhdCBQTTI1IExldmVscyAKCiMjIyMgR3JvdXBlZCBieSBSdXJhbC9VcmJhbgpgYGB7cn0KcGN0X2NoZ19hdWcgJT4lCiAgbmEub21pdCgpICU+JQogIGlubmVyX2pvaW4oLiwgc3Vic2V0X2dsYXNzLCBieSA9IGMoJ3pjdGEnID0gJ3pjdGEnLCAnd2VlaycgPSAnZGF0ZScpKSAlPiUKICBzZWxlY3QoemN0YSwgZmlyZV9jYXQsIHdlZWssIFBNMjUsIHdmX3BtMjVfaW1wLCBiaW5zLCBwY3RfY2hnX21vbl96LCBSdXJhbF9EdW1teV9SKSAlPiUKICBncm91cF9ieSh3ZWVrLHpjdGEpICU+JQogIGFycmFuZ2UoemN0YSkgJT4lCiAgZ2dwbG90KGRhdGEgPSAuLCBhZXMoeCA9IHdlZWssIHkgPSBQTTI1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gUnVyYWxfRHVtbXlfUikpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJ1cmFsX0R1bW15X1IpLCBhbHBoYSA9IC41KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCdCbHVlJywnR3JlZW4nKSkgKwogIGdlb21fc21vb3RoKHNlID0gRikgKyAKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjEgd2VlayIsIGxpbWl0cyA9IGFzLkRhdGUoYygiMjAyMC0wOC0zMSIsICIyMDIwLTEwLTEyIikpKSArCiAgbGFicyh0aXRsZT0iUE0yNSBWYWx1ZXMgYnkgRGF0ZSBhbmQgQ2F0ZWdvcnkiKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUE0yNSBWYWx1ZXMiKSArCiAgbGFicyhjb2xvcj0nTmF0aW9uJykgICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDIwLTA5LTIxIiksIHhtYXggPSBhcy5EYXRlKCIyMDIwLTEwLTEyIiksIAogICAgICAgICAgIHltaW4gPSAwLCB5bWF4ID0gMTAwICwKICAgICAgICAgICAgIGFscGhhID0gMCwgY29sb3I9ICJvcmFuZ2UiKSAgKyBmYWNldF93cmFwKHZhcnMoZmlyZV9jYXQpLCBucm93ID0gMykKYGBgCgojIyMjIEdyb3VwZWQgYnkgQWdyaWN1bHR1cmFsCmBgYHtyfQpwY3RfY2hnX2F1ZyAlPiUKICBuYS5vbWl0KCkgJT4lCiAgaW5uZXJfam9pbiguLCBzdWJzZXRfZ2xhc3MsIGJ5ID0gYygnemN0YScgPSAnemN0YScsICd3ZWVrJyA9ICdkYXRlJykpICU+JQogIHNlbGVjdCh6Y3RhLCBmaXJlX2NhdCwgd2VlaywgUE0yNSwgd2ZfcG0yNV9pbXAsIGJpbnMsIHBjdF9jaGdfbW9uX3osIEFncl9EdW1teV83NSkgJT4lCiAgZ3JvdXBfYnkod2Vlayx6Y3RhKSAlPiUKICBhcnJhbmdlKHpjdGEpICU+JQogIGdncGxvdChkYXRhID0gLiwgYWVzKHggPSB3ZWVrLCB5ID0gUE0yNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IEFncl9EdW1teV83NSkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IEFncl9EdW1teV83NSksIGFscGhhID0gLjUpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoJ0JsdWUnLCdHcmVlbicpKSArCiAgZ2VvbV9zbW9vdGgoc2UgPSBGKSArIAogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMSB3ZWVrIiwgbGltaXRzID0gYXMuRGF0ZShjKCIyMDIwLTA4LTMxIiwgIjIwMjAtMTAtMTIiKSkpICsKICBsYWJzKHRpdGxlPSJQTTI1IFZhbHVlcyBieSBEYXRlIGFuZCBDYXRlZ29yeSIpICsKICBsYWJzKHg9IkRhdGUiLCB5PSJQTTI1IFZhbHVlcyIpICsKICBsYWJzKGNvbG9yPSdOYXRpb24nKSAgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IGFzLkRhdGUoIjIwMjAtMDktMjEiKSwgeG1heCA9IGFzLkRhdGUoIjIwMjAtMTAtMTIiKSwgCiAgICAgICAgICAgeW1pbiA9IDAsIHltYXggPSAxMDAgLAogICAgICAgICAgICAgYWxwaGEgPSAwLCBjb2xvcj0gIm9yYW5nZSIpICArIGZhY2V0X3dyYXAodmFycyhmaXJlX2NhdCksIG5yb3cgPSAzKQpgYGAKCgojIyMjIEdyb3VwZWQgYnkgUG92ZXJ0eQpgYGB7cn0KcGN0X2NoZ19hdWcgJT4lCiAgbmEub21pdCgpICU+JQogIGlubmVyX2pvaW4oLiwgc3Vic2V0X2dsYXNzLCBieSA9IGMoJ3pjdGEnID0gJ3pjdGEnLCAnd2VlaycgPSAnZGF0ZScpKSAlPiUKICBzZWxlY3QoemN0YSwgZmlyZV9jYXQsIHdlZWssIFBNMjUsIHdmX3BtMjVfaW1wLCBiaW5zLCBwY3RfY2hnX21vbl96LCBQb3ZlcnR5X0R1bW15Xzc1KSAlPiUKICBncm91cF9ieSh3ZWVrLHpjdGEpICU+JQogIGFycmFuZ2UoemN0YSkgJT4lCiAgZ2dwbG90KGRhdGEgPSAuLCBhZXMoeCA9IHdlZWssIHkgPSBQTTI1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gUG92ZXJ0eV9EdW1teV83NSkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFBvdmVydHlfRHVtbXlfNzUpLCBhbHBoYSA9IC41KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCdCbHVlJywnR3JlZW4nKSkgKwogIGdlb21fc21vb3RoKHNlID0gRikgKyAKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjEgd2VlayIsIGxpbWl0cyA9IGFzLkRhdGUoYygiMjAyMC0wOC0zMSIsICIyMDIwLTEwLTEyIikpKSArCiAgbGFicyh0aXRsZT0iUE0yNSBWYWx1ZXMgYnkgRGF0ZSBhbmQgQ2F0ZWdvcnkiKSArCiAgbGFicyh4PSJEYXRlIiwgeT0iUE0yNSBWYWx1ZXMiKSArCiAgbGFicyhjb2xvcj0nTmF0aW9uJykgICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDIwLTA5LTIxIiksIHhtYXggPSBhcy5EYXRlKCIyMDIwLTEwLTEyIiksIAogICAgICAgICAgIHltaW4gPSAwLCB5bWF4ID0gMTAwICwKICAgICAgICAgICAgIGFscGhhID0gMCwgY29sb3I9ICJvcmFuZ2UiKSAgKyBmYWNldF93cmFwKHZhcnMoZmlyZV9jYXQpLCBucm93ID0gMykKYGBgCgo=